﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Utils
{

    public class ProcessHelper
    {
        private const string BASH = "/bin/bash";

        private const string CMDEXE = "cmd.exe";

        private readonly Process process;



        private ProcessHelper(ProcessStartInfo processStartInfo)
        {
            process = new Process
            {
                StartInfo = processStartInfo
            };
        }

        public Process GetProcess() => process;


        /// <summary>
        /// 启动一个进程
        /// </summary>
        /// <param name="msgCallback"></param>
        public Task Start(Action<string> msgCallback = null, Action closeCallback = null)
        {
            return Task.Factory.StartNew(async () =>
             {
                 process.Start();
                 try
                 {
                     while (!process.HasExited)
                     {
                         string str = await process.StandardOutput.ReadLineAsync();
                         if (string.IsNullOrEmpty(str))
                         {
                             if (process.StandardOutput.EndOfStream)
                                 break;
                             continue;
                         }
                         msgCallback?.Invoke(str);
                     }
                     string err = await process.StandardError.ReadToEndAsync();
                     if (!string.IsNullOrEmpty(err))
                         msgCallback?.Invoke(err);
                 }
                 catch
                 {
                 }
                 closeCallback?.Invoke();
             }, TaskCreationOptions.LongRunning);
        }
        public Task<string> StartWaitResult()
        {
            return Task.Factory.StartNew(async () =>
            {
                process.Start();
                List<string> strs = new List<string>();
                try
                {
                    while (!process.HasExited)
                    {
                        string str = await process.StandardOutput.ReadLineAsync();
                        if (string.IsNullOrEmpty(str))
                        {
                            if (process.StandardOutput.EndOfStream)
                                break;
                            continue;
                        }
                        strs.Add(str);


                    }
                    string err = await process.StandardError.ReadToEndAsync();
                    if (!string.IsNullOrEmpty(err))
                        strs.Add(err);
                }
                catch
                {
                }
                return string.Join("\r\n", strs);
            }, TaskCreationOptions.LongRunning).Unwrap();
        }

        /// <summary>
        /// 杀死当前进程
        /// </summary>
        public void Kill()
        {
            process.StandardInput.Close();
            process.Kill();
            process.Close();
            process.Dispose();
        }



        /// <summary>
        /// 运行程序
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="arguments"></param>
        /// <param name="workingDirectory"></param>
        /// <returns></returns>
        public static ProcessHelper Run(string fileName, string arguments = "", string workingDirectory = null)
        {
            ProcessStartInfo psi = new ProcessStartInfo();
            psi.FileName = fileName;
            psi.UseShellExecute = false;
            psi.RedirectStandardOutput = true;
            psi.RedirectStandardError = true;
            psi.RedirectStandardInput = true;
            psi.CreateNoWindow = true;
            psi.WorkingDirectory = workingDirectory;
            psi.Arguments = arguments;
            return new ProcessHelper(psi);
        }

        public static bool IsWindows()
        {
            return RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
        }

        public static bool IsLinux()
        {
            return RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
        }
        /// <summary>
        /// 运行命令
        /// </summary>
        /// <param name="cmdString"></param>
        /// <param name="workingDirectory"></param>
        /// <returns></returns>
        public static ProcessHelper RunCmd(string cmdString, string workingDirectory = null)
        {
            if (IsWindows())
            {
                return RunWindows(cmdString, workingDirectory);
            }
            else if (IsLinux())
            {
                return RunLinux(cmdString, workingDirectory);
            }
            else
            {
                throw new NotSupportedException("当前系统不支持");
            }
        }



        private static ProcessHelper RunLinux(string cmdString, string workingDirectory)
        {
            return Run(BASH, $"-c \"{cmdString.Replace("\"", "\\\"")}\"", workingDirectory);
        }

        private static ProcessHelper RunWindows(string cmdString, string workingDirectory)
        {
            return Run(CMDEXE, $"/c {cmdString}", workingDirectory);
        }

    }
}
